package com.tengju.bff.interfaces.covercharge.controller.admin;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.idanchuang.component.config.apollo.util.ConfigUtil;
import com.idanchuang.component.redis.util.DRedisLocks;
import com.tengju.bff.interfaces.covercharge.constant.*;
import com.tengju.bff.interfaces.covercharge.entity.dto.RegisteredInfo;
import com.tengju.bff.interfaces.covercharge.entity.dto.WithdrawalReason;
import com.tengju.bff.interfaces.covercharge.entity.po.*;
import com.tengju.bff.interfaces.covercharge.entity.vo.*;
import com.tengju.bff.interfaces.covercharge.service.*;
import com.tengju.bff.interfaces.covercharge.util.DateTimeUtils;
import com.tengju.bff.interfaces.covercharge.util.redis.HeavyUtil;
import com.tengju.bff.interfaces.shared.ApiResponse;
import com.tengju.bff.interfaces.shared.export.BillApplyRecordExportQuery;
import com.tengju.bff.interfaces.shared.servlet.ManageEntrance;
import com.tengju.bff.interfaces.shared.servlet.ManageUtil;
import com.tengju.bff.interfaces.shared.servlet.ServletContextUtil;
import com.tengju.export.application.ExportService;
import com.tengju.export.domain.record.ExportDataType;
import com.tengju.export.domain.record.ExportFileType;
import com.tengju.user.application.user.UserDataAuthService;
import com.tengju.user.domain.model.user.Staff;
import com.tengju.user.domain.model.user.StaffId;
import com.tengju.user.domain.model.user.UserIdCode;
import com.tengju.user.domain.model.user.UserInfo;
import com.tengju.user.domain.service.UserDocService;
import com.zoi7.component.core.exception.ServiceException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * @author fwy
 */
@Api(value = "applyRecord", tags = "Admin提现申请记录")
@RestController
@Slf4j
@RequestMapping("/manage/bill/applyRecord")
@ManageEntrance
public class AdminApplyRecordController {

    @Autowired
    private IServiceLetaxWithdrawLogService serviceLetaxWithdrawLogService;

    @Autowired
    private IServiceSelfCertificationWithdrawService serviceSelfCertificationWithdrawService;

    @Autowired
    private IServiceSelfCertificationService serviceSelfCertificationService;

    @Autowired
    private IAttachmentService attachmentService;

    @Autowired
    private IServiceInvoiceShippingLogService serviceInvoiceShippingLogService;

//    @Autowired
//    private UserInfoRepository userInfoRepository;

    @Autowired
    private UserDocService userDocService;

    @Autowired
    private IAdminApplyRecordService adminApplyRecordService;

    @Autowired
    private IServiceSignService serviceSignService;

    @Autowired
    private SelfCertificationService selfCertificationService;
    @Autowired
    private ExportService exportService;

    private final static Integer APPLY_STATUS = 1;

    //每页数量
    private final static Integer PAGE_SIZE = 10000;

    private final static Integer SPLIT_MAX_NUM = 500;

    @Resource
    private ThreadPoolExecutor threadPoolExecutor;
    @Resource
    private IRoleDesensitService roleDesensitService;
    @Resource
    private UserDataAuthService userDataAuthService;

    @GetMapping("/getRegistration")
    @ApiOperation(value = "注册个体户提现申请记录", notes = "注册个体户提现申请记录")
    @RequiresRoles("sso")
    public ApiResponse<IPage<AdminRegistrationQueryVo>> getRegistration(String codeId,
                                                                        String mobile,
                                                                        String name,
                                                                        String taxNo,
                                                                        String cardNo,
                                                                        String platformCode,
                                                                        Integer status,
                                                                        String date,
                                                                        @RequestParam String appCode,
                                                                        @RequestParam Long ssoUserId,
                                                                        @RequestParam(defaultValue = "0", name = "pageNo", required = true) Integer pageNo,
                                                                        @RequestParam(defaultValue = "10", name = "limit", required = true) Integer limit) {
        if (StringUtils.isNotBlank(mobile)) {
            try {
                UserInfo userInfo = userDocService.searchUserByIdCodeOrMobile(null, mobile);
                if (userInfo != null) {
                    codeId = userInfo.getIdCode().toString();
                }
            } catch (Exception e) {
                log.info("注册个体户提现申请记录根据手机号查询用户信息异常：{}", e.getMessage());
                throw new ServiceException("根据手机号码获取用户信息失败");
            }
        }

        //如果传入的时间不为空，修改成周期内的时间
        String startDate = null;
        String endDate = null;
        if (StringUtils.isNotBlank(date)) {
            Date sDate = DateTimeUtils.addMonths(DateUtil.parse(date, DateTimeUtils.MONTH_FORMAT), -1);
            String cycleDay = ConfigUtil.getConfig().getString("withdraw.cycle.day", "10");
            startDate = DateTimeUtils.parseDateAsString(sDate, DateTimeUtils.MONTH_FORMAT) + "-" + (Integer.parseInt(cycleDay) + 1) + " 00:00:00";
            endDate = date + "-" + (Integer.parseInt(cycleDay) + 1) + " 00:00:00";
        }
        Page<AdminRegistrationQueryVo> result = serviceLetaxWithdrawLogService.queryPageRegistration(new Page<>(pageNo, limit), codeId, name, taxNo, cardNo, platformCode, status, startDate, endDate);
        Staff staff = ManageUtil.getOperateUser();
        log.info("[支付后台][注册个体户提现申请记录][查看用户:{}]", staff.getStaffId().getValue());
        result.setRecords(userDataAuthService.dataMasking(result.getRecords(), staff.getStaffId()));
        return ApiResponse.newSuccess(result);
    }

    @GetMapping("/getPersonal")
    @ApiOperation(value = "个人提现申请记录", notes = "个人提现申请记录")
    public ApiResponse<IPage<AdminRegistrationQueryVo>> getPersonal(String codeId,
                                                                    String mobile,
                                                                    String name,
                                                                    String cardNo,
                                                                    String platformCode,
                                                                    Integer status,
                                                                    String date,
                                                                    @RequestParam String appCode,
                                                                    @RequestParam Long ssoUserId,
                                                                    @RequestParam(defaultValue = "0", name = "pageNo", required = true) Integer pageNo,
                                                                    @RequestParam(defaultValue = "10", name = "limit", required = true) Integer limit) {
        if (StringUtils.isNotBlank(mobile)) {
            try {
                UserInfo userInfo = userDocService.searchUserByIdCodeOrMobile(null, mobile);
                if (userInfo != null) {
                    codeId = userInfo.getIdCode().toString();
                }
            } catch (Exception e) {
                log.info("注册个体户提现申请记录根据手机号查询用户信息异常：{}", e.getMessage());
                throw new ServiceException("根据手机号码获取用户信息失败");
            }
        }
        //如果传入的时间不为空，修改成周期内的时间
        String startDate = null;
        String endDate = null;
        if (StringUtils.isNotBlank(date)) {
            Date sDate = DateTimeUtils.addMonths(DateUtil.parse(date, DateTimeUtils.MONTH_FORMAT), -1);
            String cycleDay = ConfigUtil.getConfig().getString("withdraw.cycle.day", "10");
            startDate = DateTimeUtils.parseDateAsString(sDate, DateTimeUtils.MONTH_FORMAT) + "-" + (Integer.parseInt(cycleDay) + 1) + " 00:00:00";
            endDate = date + "-" + (Integer.parseInt(cycleDay) + 1) + " 00:00:00";
        }
        Page<AdminRegistrationQueryVo> result = serviceLetaxWithdrawLogService.queryPagePerson(new Page<>(pageNo, limit), codeId, name, cardNo, platformCode, status, startDate, endDate);
        log.info("[支付后台][个人提现申请记录][查看用户:{}]", ssoUserId);
        return ApiResponse.newSuccess(roleDesensitService.checkDesensit(result, appCode, ssoUserId));
    }

    @GetMapping("/getSelfCertified")
    @ApiOperation(value = "自认证提现申请记录", notes = "自认证提现申请记录")
    @RequiresRoles("sso")
    public ApiResponse<IPage<AdminSelfCertificationQueryVo>> getSelfCertified(String codeId,
                                                                              String mobile,
                                                                              String name,
                                                                              String platformCode,
                                                                              Integer status,
                                                                              Integer type,
                                                                              Integer invoice,
                                                                              String startDate,
                                                                              String endDate,
                                                                              @RequestParam String appCode,
                                                                              @RequestParam Long ssoUserId,
                                                                              @RequestParam(defaultValue = "0", name = "pageNo", required = true) Integer pageNo,
                                                                              @RequestParam(defaultValue = "10", name = "limit", required = true) Integer limit) {
        if (StringUtils.isNotBlank(mobile)) {
            try {
                UserInfo userInfo = userDocService.searchUserByIdCodeOrMobile(null, mobile);
                if (userInfo != null) {
                    codeId = userInfo.getIdCode().toString();
                }
            } catch (Exception e) {
                log.info("自认证提现申请记录根据手机号查询用户信息异常：", e.getMessage());
                throw new ServiceException("根据手机号码获取用户信息失败");
            }
        }
        Page<AdminSelfCertificationQueryVo> result = serviceSelfCertificationWithdrawService.queryPageCertification(new Page<>(pageNo, limit), codeId, name, invoice, platformCode, status, startDate, endDate, type, null);
        Staff staff = ManageUtil.getOperateUser();
        log.info("[支付后台][自认证提现申请记录][查看用户:{}]", staff.getStaffId().getValue());
        result.setRecords(userDataAuthService.dataMasking(result.getRecords(), staff.getStaffId()));
        return ApiResponse.newSuccess(result);
    }

    @GetMapping("/getSinceCertificationRecordFunds")
    @ApiOperation(value = "自认证资金记录", notes = "自认证资金记录")
    @RequiresRoles("sso")
    public ApiResponse<IPage<AdminSelfCertificationQueryVo>> getSinceCertificationRecordFunds(String codeId,
                                                                                              String mobile,
                                                                                              String name,
                                                                                              String platformCode,
                                                                                              Integer status,
                                                                                              Integer type,
                                                                                              Integer invoice,
                                                                                              String startDate,
                                                                                              String endDate,
                                                                                              @RequestParam(defaultValue = "0", name = "pageNo", required = true) Integer pageNo,
                                                                                              @RequestParam(defaultValue = "10", name = "limit", required = true) Integer limit) {
        if (StringUtils.isNotBlank(mobile)) {
            try {
                UserInfo userInfo = userDocService.searchUserByIdCodeOrMobile(null, mobile);
                if (userInfo != null) {
                    codeId = userInfo.getIdCode().toString();
                }
            } catch (Exception e) {
                log.info("自认证资金记录根据手机号查询用户信息异常：{}", e.getMessage());
                throw new ServiceException("根据手机号码获取用户信息失败");
            }
        }
        IPage<AdminSelfCertificationQueryVo> result = serviceSelfCertificationWithdrawService.queryPageCertificationPaid(new Page<>(pageNo, limit), codeId, name, invoice, platformCode, status, startDate, endDate, type);
        Staff staff = ManageUtil.getOperateUser();
        result.setRecords(userDataAuthService.dataMasking(result.getRecords(), staff.getStaffId()));
        return ApiResponse.newSuccess(result);
    }

    @GetMapping("/moneyTotal")
    @ApiOperation(value = "自认证资金统计金额", notes = "自认证资金统计金额")
    @RequiresRoles("sso")
    public ApiResponse<AdminSelfCertificationMoneyTotalVo> moneyTotal(String codeId,
                                                                      String mobile,
                                                                      String name,
                                                                      String platformCode,
                                                                      Integer status,
                                                                      Integer type,
                                                                      Integer invoice,
                                                                      String startDate,
                                                                      String endDate,
                                                                      @RequestParam(defaultValue = "0", name = "pageNo", required = true) Integer pageNo,
                                                                      @RequestParam(defaultValue = "10", name = "limit", required = true) Integer limit) {
        if (StringUtils.isNotBlank(mobile)) {
            try {
                UserInfo userInfo = userDocService.searchUserByIdCodeOrMobile(null, mobile);
                if (userInfo != null) {
                    codeId = userInfo.getIdCode().toString();
                }
            } catch (Exception e) {
                log.info("自认证资金记录根据手机号查询用户信息异常：{}", e.getMessage());
                throw new ServiceException("根据手机号码获取用户信息失败");
            }
        }
        AdminSelfCertificationMoneyTotalVo result = serviceSelfCertificationWithdrawService.queryCertificationPaidMoneyTotal(codeId, name, invoice, platformCode, status, startDate, endDate, type);
        return ApiResponse.newSuccess(result);
    }

    @GetMapping("/listConfig")
    @ResponseBody
    @ApiOperation(value = "提现列表配置", notes = "提现列表配置项")
    @RequiresRoles("sso")
    public ApiResponse<WithdrawListConfigRes> withdrawalListConfiguration(@Param("withdrawalState") String withdrawalState,
                                                                          @Param("applyAtStart") String applyAtStart,
                                                                          @Param("applyAtEnd") String applyAtEnd,
                                                                          @Param("userIdCode") String userIdCode,
                                                                          @Param("mobile") String mobile,
                                                                          @Param("bankNo") String bankNo,
                                                                          @Param("amount") String amount) {
        WithdrawListConfigRes config = new WithdrawListConfigRes();
        Integer batchCount = serviceSelfCertificationWithdrawService.getRunningBatchCount();
        config.setBatchCount(batchCount);

        return ApiResponse.newSuccess(config);
    }

    @PostMapping("/updateRegistrationStatus")
    @ApiOperation(value = "注册个体户,个人提现申请审批", notes = "注册个体户,个人提现申请审批")
    public ApiResponse<?> updateRegistrationStatus(@RequestBody JSONObject jsonObject) {
        Integer applyId = jsonObject.getInteger("applyId");
        String remark = jsonObject.getString("remark");
        Integer status = jsonObject.getInteger("status");
        String approvers = jsonObject.getString("approvers");

        return DRedisLocks.runWithLock(BizConstants.UPDATE_APPLY_REG + applyId, 500, () -> {
            try {
                adminApplyRecordService.updateRegistrationStatus(applyId, remark, status, approvers);
                return ApiResponse.newSuccess();
            } catch (Exception e) {
                log.error("company withdrawalApply error", e);
                return ApiResponse.newFailure(CoverChargeErrorCode.SYS_ERROR.getCode(), e.getMessage());
            }
        });
    }

    @RequiresRoles("sso")
    @PostMapping("/updateRegistrationStatusList")
    @ApiOperation(value = "注册个体户,个人提现申请批量审批", notes = "注册个体户,个人提现申请批量审批")
    public ApiResponse<?> updateRegistrationStatusList(@RequestBody JSONObject jsonObject) {
        String applyIds = jsonObject.getString("applyIds");
        List<Integer> ids = JSON.parseArray(applyIds, Integer.class);
        if (ids == null || ids.size() <= 0) {
            throw new ServiceException("申请编号传入不能为空");
        }
        String remark = jsonObject.getString("remark");
        Integer status = jsonObject.getInteger("status");
        String approvers = jsonObject.getString("approvers");
        return DRedisLocks.runWithLock(BizConstants.UPDATE_APPLY_REG + applyIds, 500, () -> {
            try {
                for (Integer applyId : ids) {
                    adminApplyRecordService.updateRegistrationStatus(applyId, remark, status, approvers);
                }
                return ApiResponse.newSuccess();
            } catch (Exception e) {
                log.error("company withdrawalApply error", e);
                return ApiResponse.newFailure(CoverChargeErrorCode.SYS_ERROR.getCode(), e.getMessage());
            }
        });
    }

    @PostMapping("/updateAllPersonStatusList")
    @ApiOperation(value = "个人提现申请全量审批", notes = "个人提现申请全量审批")
    public ApiResponse<?> updateAllPersonStatusList(@RequestBody JSONObject jsonObject) {
        //1.判断是否传入周期时间(此条件为必要条件)
        String date = jsonObject.getString("date");
        if (StringUtils.isBlank(date)) {
            log.info("[服务费后台][个人提现申请记录][全量审批失败,周期时间为空]");
            return ApiResponse.newFailure(CoverChargeErrorCode.PARAM_ERROR.getCode(), "请选择周期时间！");
        }
        //2.判断通过手机号能否查询到记录
        String mobile = jsonObject.getString("mobile");
        String codeId = jsonObject.getString("codeId");
        if (StringUtils.isNotBlank(mobile)) {
            try {
                UserInfo userInfo = userDocService.searchUserByIdCodeOrMobile(null, mobile);
                if (userInfo != null) {
                    codeId = userInfo.getIdCode().toString();
                } else {
                    log.info("[服务费后台][个人提现申请记录][全量审批失败,未能根据手机号查询到数据][mobile:{}]", mobile);
                    return ApiResponse.newFailure(CoverChargeErrorCode.PARAM_ERROR.getCode(), "未能根据手机号查询到相关数据!");
                }
            } catch (Exception e) {
                log.info("[服务费后台][个人提现申请记录][全量审批失败,根据手机号查询数据异常][mobile:{}],{}", mobile, e.getMessage());
                return ApiResponse.newFailure(CoverChargeErrorCode.PARAM_ERROR.getCode(), "未能根据手机号查询到相关数据!");
            }
        }
        //3.将传入时间修改成周期内的时间
        Date sDate = DateTimeUtils.addMonths(DateUtil.parse(date, DateTimeUtils.MONTH_FORMAT), -1);
        String cycleDay = ConfigUtil.getConfig().getString("withdraw.cycle.day", "10");
        String startDate =
                DateTimeUtils.parseDateAsString(sDate, DateTimeUtils.MONTH_FORMAT) + "-" + (Integer.parseInt(cycleDay)
                        + 1) + " 00:00:00";
        String endDate = date + "-" + (Integer.parseInt(cycleDay) + 1) + " 00:00:00";
        //4.查询符合条件,状态为申请中的list
        List<ServiceLetaxWithdrawLog> applyList = serviceLetaxWithdrawLogService
                .queryPersonApplyList(codeId, jsonObject.getString("cardNo"), jsonObject.getString("platformCode"),
                        APPLY_STATUS, startDate, endDate);
        if (CollectionUtils.isEmpty(applyList)) {
            log.info("[服务费后台][个人提现申请记录][全量审批失败,无可审核记录][requestParam:{}]", jsonObject);
            return ApiResponse.newFailure(CoverChargeErrorCode.BUSINESS_ERROR.getCode(), "该查询条件下无可审核记录");
        }
        int status = jsonObject.getInteger("status");
        String approvers = jsonObject.getString("approvers");
        return DRedisLocks.runWithLock(BizConstants.UPDATE_APPLY_REG + applyList, 500, () -> {
            try {
                //5.多线程全量审核更新
                batchUpdate(applyList, status, approvers);
                return ApiResponse.newSuccess();
            } catch (Exception e) {
                log.error("[服务费后台][个人提现申请记录][全量审批失败,有异常抛出]", e);
                return ApiResponse.newFailure(CoverChargeErrorCode.SYS_ERROR.getCode(), e.getMessage());
            }
        });
    }

    @RequiresRoles("sso")
    @PostMapping("/updateAllRegistrationStatusList")
    @ApiOperation(value = "注册个体户提现申请全量审批", notes = "注册个体户提现申请全量审批")
    public ApiResponse<?> updateAllRegistrationStatusList(@RequestBody JSONObject jsonObject) {
        //1.判断是否传入周期时间(此条件为必要条件)
        String date = jsonObject.getString("date");
        if (StringUtils.isBlank(date)) {
            log.info("[服务费后台][注册个体户提现申请记录][全量审批失败,周期时间为空]");
            return ApiResponse.newFailure(CoverChargeErrorCode.PARAM_ERROR.getCode(), "请选择周期时间！");
        }
        //2.判断通过手机号能否查询到记录
        String mobile = jsonObject.getString("mobile");
        String codeId = jsonObject.getString("codeId");
        if (StringUtils.isNotBlank(mobile)) {
            try {
                UserInfo userInfo = userDocService.searchUserByIdCodeOrMobile(null, mobile);
                if (userInfo != null) {
                    codeId = userInfo.getIdCode().toString();
                } else {
                    log.info("[服务费后台][注册个体户提现申请记录][全量审批失败,未能根据手机号查询到数据][mobile:{}]", mobile);
                    return ApiResponse.newFailure(CoverChargeErrorCode.PARAM_ERROR.getCode(), "未能根据手机号查询到相关数据!");
                }
            } catch (Exception e) {
                log.info("[服务费后台][注册个体户提现申请记录][全量审批失败,根据手机号查询数据异常][mobile:{}],{}", mobile, e.getMessage());
                return ApiResponse.newFailure(CoverChargeErrorCode.PARAM_ERROR.getCode(), "未能根据手机号查询到相关数据!");
            }
        }
        //3.将传入时间修改成周期内的时间
        Date sDate = DateTimeUtils.addMonths(DateUtil.parse(date, DateTimeUtils.MONTH_FORMAT), -1);
        String cycleDay = ConfigUtil.getConfig().getString("withdraw.cycle.day", "10");
        String startDate =
                DateTimeUtils.parseDateAsString(sDate, DateTimeUtils.MONTH_FORMAT) + "-" + (Integer.parseInt(cycleDay)
                        + 1) + " 00:00:00";
        String endDate = date + "-" + (Integer.parseInt(cycleDay) + 1) + " 00:00:00";
        //4.查询符合条件,状态为申请中的list
        List<ServiceLetaxWithdrawLog> applyList = serviceLetaxWithdrawLogService
                .queryRegisterApplyList(codeId, jsonObject.getString("cardNo"), jsonObject.getString("platformCode"),
                        jsonObject.getString("taxNo"), APPLY_STATUS, startDate, endDate);
        if (CollectionUtils.isEmpty(applyList)) {
            log.info("[服务费后台][注册个体户提现申请记录][全量审批失败,无可审核记录][requestParam:{}]", jsonObject);
            return ApiResponse.newFailure(CoverChargeErrorCode.BUSINESS_ERROR.getCode(), "该查询条件下无可审核记录");
        }
        int status = jsonObject.getInteger("status");
        String approvers = jsonObject.getString("approvers");
        return DRedisLocks.runWithLock(BizConstants.UPDATE_APPLY_REG + applyList, 500, () -> {
            try {
                //5.多线程全量审核更新
                batchUpdate(applyList, status, approvers);
                return ApiResponse.newSuccess();
            } catch (Exception e) {
                log.error("[服务费后台][注册个体户提现申请记录][全量审批失败,有异常抛出]", e);
                return ApiResponse.newFailure(CoverChargeErrorCode.SYS_ERROR.getCode(), e.getMessage());
            }
        });
    }

    @GetMapping("/getRegistrationDetail")
    @ApiOperation(value = "获取注册个体户（个人）提现详情", notes = "获取注册个体户（个人）提现详情")
    public ApiResponse<AdminRegistrationQueryVo> getRegistrationDetail(Integer applyId) {
        ServiceLetaxWithdrawLog log = serviceLetaxWithdrawLogService.getById(applyId);
        if (null == log) {
            throw new ServiceException("该条审批记录不存在！");
        }
        AdminRegistrationQueryVo adminRegistrationQueryVo = new AdminRegistrationQueryVo();
        BeanUtils.copyProperties(log, adminRegistrationQueryVo);
        if (log.getAuthType().equals(CooperationEnum.PERSONAL.getCode())) {
            JSONObject result = JSONObject.parseObject(log.getRegisteredInfo());
            adminRegistrationQueryVo.setName(result.getString("idcard_name"));
            adminRegistrationQueryVo.setBankName(result.getString("bank_name"));
            adminRegistrationQueryVo.setBankNo(result.getString("bank_no"));
        } else {
            List<RegisteredInfo> infos = JSON.parseArray(log.getRegisteredInfo(), RegisteredInfo.class);
            for (RegisteredInfo info : infos) {
                adminRegistrationQueryVo.setName(info.getName());
                adminRegistrationQueryVo.setBankName(info.getBankName());
                adminRegistrationQueryVo.setBankNo(info.getBankNo());
                adminRegistrationQueryVo.setIdcardName(info.getIdcardName());
                adminRegistrationQueryVo.setMobile(info.getPhoneNumber());
                //注册工商户多余信息
                adminRegistrationQueryVo.setMerchantName(info.getMerchantName());
                adminRegistrationQueryVo.setMerchantTaxNumber(info.getMerchantTaxNumber());
            }
        }
        return ApiResponse.newSuccess(adminRegistrationQueryVo);
    }

    @RequiresRoles("sso")
    @GetMapping("/getSelfDetail")
    @ApiOperation(value = "获取自认证提现详情", notes = "获取自认证提现详情")
    public ApiResponse<AdminSelfCertificationDetail> getSelfDetail(Integer applyId, Long ssoUserId) {
        ServiceSelfCertificationWithdraw draw = serviceSelfCertificationWithdrawService.getById(applyId);
        if (null == draw) {
            throw new ServiceException("该条审批记录不存在！");
        }
        AdminSelfCertificationDetail detail = new AdminSelfCertificationDetail();
        BeanUtils.copyProperties(draw, detail);
        //查询自认证信息
        ServiceSelfCertification serviceSelfCertification = serviceSelfCertificationService.getById(draw.getSelfCertificationId());
        detail.setBankName(serviceSelfCertification.getBankName());
        detail.setBankNo(serviceSelfCertification.getBankNo());
        detail.setCompanyName(serviceSelfCertification.getCompanyName());
        detail.setCompanyAddress(serviceSelfCertification.getCompanyAddress());
        detail.setCompanyNo(serviceSelfCertification.getCompanyNo());
        detail.setIdcardNo(serviceSelfCertification.getIdcardNo());
        detail.setIdcardName(serviceSelfCertification.getIdcardName());
        //获取代理信息
        try {
            UserInfo userInfo = userDocService.searchUserByIdCodeOrMobile(new UserIdCode(detail.getIdCode()), null);

            detail.setName(userInfo.getName());
            detail.setMobile(userInfo.getMobile());
        } catch (Exception e) {
            log.error("获取认证申请记录详情获取用户信息失败：{}", e.getMessage());
            throw new ServiceException("获取用户信息失败！");
        }
        //营业执照地址
        String businessImgUrl = attachmentService.getUrl(serviceSelfCertification.getBusinessImg());
        detail.setBusinessImg(businessImgUrl);
        //发票照片地址
        String[] imgs = draw.getInvoiceImg().split(",");
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < imgs.length; i++) {
            String invoiceImgUrl = attachmentService.getUrl(imgs[i]);
            if (i == 0) {
                sb.append(invoiceImgUrl);
            } else {
                sb.append(",").append(invoiceImgUrl);
            }
        }
        detail.setInvoiceImg(sb.toString());
        List<WithdrawalReason> withdrawalReasonList = JSON.parseArray(draw.getReasonNew(), WithdrawalReason.class);
        detail.setReasonNew(withdrawalReasonList);
        log.info("[支付后台][认证企业/个体户提现-获取自认证提现详情][查看用户:{}]", ssoUserId);
        return ApiResponse.newSuccess(detail);
    }

    @PostMapping("/updateSelfStatus")
    @ApiOperation(value = "自认证提现申请审批", notes = "自认证提现申请审批")
    public ApiResponse<?> updateSelfStatus(@RequestBody JSONObject jsonObject) {
        Integer applyId = jsonObject.getInteger("applyId");
        String remark = jsonObject.getString("remark");
        Integer status = jsonObject.getInteger("status");
        String approvers = jsonObject.getString("approvers");
        String shippingNo = jsonObject.getString("shippingNo");
        String expressName = jsonObject.getString("expressName");
        return DRedisLocks.runWithLock(BizConstants.UPDATE_APPLY_COMPANY + applyId, 500, () -> {
            try {
                adminApplyRecordService.updateSelfStatus(remark, applyId, status, approvers, shippingNo, expressName);
                return ApiResponse.newSuccess();
            } catch (Exception e) {
                log.error("company withdrawalApply error", e);
                return ApiResponse.newFailure(CoverChargeErrorCode.SYS_ERROR.getCode(), e.getMessage());
            }
        });
    }

    @RequiresRoles("sso")
    @GetMapping("/getVerifyResult")
    @ApiOperation(value = "获取自认证审核结果", notes = "获取自认证审核结果")
    public ApiResponse<AdminVerifyDetail> getVerifyResult(Integer applyId) {
        ServiceSelfCertificationWithdraw draw = serviceSelfCertificationWithdrawService.getById(applyId);
        if (draw == null) {
            throw new ServiceException("找不到该审批记录");
        }
        AdminVerifyDetail detail = new AdminVerifyDetail();
        BeanUtils.copyProperties(draw, detail);
        //获取邮寄发票信息
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("self_withdraw_id", draw.getId());
        queryWrapper.eq("type", 1);
        ServiceInvoiceShippingLog shippingLog = serviceInvoiceShippingLogService.getOne(queryWrapper);
        if (shippingLog != null) {
            detail.setShippingNo(shippingLog.getShippingNo());
            detail.setExpressName(shippingLog.getExpressName());
            detail.setCreatedAt(shippingLog.getCreatedAt());
            //查询图片
            String url = attachmentService.getUrl(String.valueOf(shippingLog.getImgId()));
            if (StringUtils.isNotBlank(url)) {
                detail.setImgId(url);
            }
        }
        //获取公司邮寄信息
        QueryWrapper queryWrapper2 = new QueryWrapper();
        queryWrapper2.eq("self_withdraw_id", draw.getId());
        queryWrapper2.eq("type", 2);
        ServiceInvoiceShippingLog logs = serviceInvoiceShippingLogService.getOne(queryWrapper2);
        if (logs != null) {
            detail.setBackExpressName(logs.getExpressName());
            detail.setBackShippingNo(logs.getShippingNo());
        }
        return ApiResponse.newSuccess(detail);
    }

    @GetMapping("/export")
    @ApiOperation(value = "导出自认证提现审批列表")
    public ApiResponse<Object> export(AdminSelfCertificationQuery adminSelfCertificationQuery) {
        StaffId staffId = ServletContextUtil.getServletContext().getStaffId();
        String realName = ServletContextUtil.getServletContext().getRealName();

        BillApplyRecordExportQuery exportQuery = new BillApplyRecordExportQuery();
        exportQuery.setPageNo(1);
        exportQuery.setLimit(100000);
        exportQuery.setIdCode(adminSelfCertificationQuery.getIdCode());
        exportQuery.setUserName(adminSelfCertificationQuery.getUserName());
        exportQuery.setInvoice(adminSelfCertificationQuery.getInvoice());
        exportQuery.setPlatformCode(adminSelfCertificationQuery.getPlatformCode());
        exportQuery.setStatus(adminSelfCertificationQuery.getStatus());
        exportQuery.setStartDate(adminSelfCertificationQuery.getStartDate());
        exportQuery.setEndDate(adminSelfCertificationQuery.getEndDate());
        exportQuery.setType(adminSelfCertificationQuery.getType());
        exportQuery.setExportType(adminSelfCertificationQuery.getExportType());
        exportQuery.setStaffId(staffId);

        exportService.exportData("自认证申请记录", ExportFileType.XLSX,
                "billApplyRecordExportDataSourceRepository",
                ExportDataType.TABLE, exportQuery,
                staffId.getValue(), realName);
        return ApiResponse.newSuccess();
    }

    /**
     * @return void
     * @Author xx
     * @Description 多线程全量审核更新
     * @Date: 2020/7/1 9:42
     * @Param [applyList, status, approvers]
     **/
    private void batchUpdate(List<ServiceLetaxWithdrawLog> applyList, int status, String approvers) {
        if (CollectionUtils.isNotEmpty(applyList)) {
            //1.全量更新,超过500个,考虑多线程处理;
            if (applyList.size() > SPLIT_MAX_NUM) {
                try {
                    for (int i = 0; i < applyList.size(); i = i + SPLIT_MAX_NUM) {
                        List<ServiceLetaxWithdrawLog> subapplyList = applyList.stream().skip(i).limit(SPLIT_MAX_NUM)
                                .collect(Collectors.toList());
                        threadPoolExecutor.execute(() -> {
                            for (ServiceLetaxWithdrawLog list : subapplyList) {
                                adminApplyRecordService
                                        .updateRegistrationStatus(Integer.parseInt(String.valueOf(list.getId())), "",
                                                status, approvers);
                            }
                        });
                    }
                } catch (Exception e) {
                    log.error("[服务费后台][个人提现申请记录][全量审批失败,多线程执行过程中有异常抛出]", e);
                }
                return;
            }
            //2.处理量小于最大值，直接做审核更新操作
            for (ServiceLetaxWithdrawLog list : applyList) {
                adminApplyRecordService
                        .updateRegistrationStatus(Integer.parseInt(String.valueOf(list.getId())), "", status,
                                approvers);
            }
        }
    }

    @PostMapping("/certificationCancel")
    @ResponseBody
    @ApiOperation(value = "取消服务费提现申请")
    public ApiResponse<?> cancel(@RequestBody AdminWithdrawalApplyCancel adminWithdrawalApplyCancel) {
        log.info("取消服务费提现申请...{}", JSON.toJSONString(adminWithdrawalApplyCancel));
        Assert.notNull(adminWithdrawalApplyCancel.getId(), "提现申请ID不能为空");
        Assert.notNull(adminWithdrawalApplyCancel.getIdCode(), "代理idCode不能为空");
        Assert.notNull(adminWithdrawalApplyCancel.getPlatformCode(), "平台不能为空");

        ServiceSign serviceSignParam = new ServiceSign();
        serviceSignParam.setIdCode(adminWithdrawalApplyCancel.getIdCode());
        serviceSignParam.setPlatformCode(adminWithdrawalApplyCancel.getPlatformCode());
        ServiceSign serviceSign = serviceSignService.getOne(new QueryWrapper<>(serviceSignParam));
        Assert.isTrue(serviceSign != null && CoverChargeEnum.CommonStatus.YES.getName().equals(serviceSign.getIsSigned()), "未签约");

        return DRedisLocks.runWithLock(BizConstants.WITHDRAWAL_CANCEL + adminWithdrawalApplyCancel.getIdCode(), 500, () -> {
            try {
                if (SignIdentityEnum.certified_individual.toString().equals(serviceSign.getCurrentIdentity())
                        || SignIdentityEnum.certified_business.toString().equals(serviceSign.getCurrentIdentity())) {
                    selfCertificationService.withdrawalApplyCancel(adminWithdrawalApplyCancel.getIdCode(), adminWithdrawalApplyCancel.getPlatformCode(), adminWithdrawalApplyCancel.getId());
                }
                return ApiResponse.newSuccess();
            } catch (Exception e) {
                log.error("自认证后台取消报错", e);
                return ApiResponse.newFailure(CoverChargeErrorCode.SYS_ERROR.getCode(), e.getMessage());
            }
        });
    }

    @PostMapping("/batchProcessingWithdrawalRecord")
    @ResponseBody
    @ApiOperation(value = "批量处理自认证提现记录", notes = "批量处理自认证提现记录")
    public ApiResponse<?> batchProcessingWithdrawalRecord(@RequestBody AdminSinceCertificationBatchMoneyVo adminSinceCertificationBatchMoneyVo) {
        return DRedisLocks.runWithLock(BizConstants.SINCE_CERTIFICATION_WITHDRAWAL, 5000, () -> {
            try {
                List<ServiceSelfCertificationWithdraw> serviceSelfCertificationWithdrawList = null;
                try {
                    //userIdCode实际为userId
                    serviceSelfCertificationWithdrawList = serviceSelfCertificationWithdrawService.queryPaidBatchList(adminSinceCertificationBatchMoneyVo.getCycleAddIds());
                } catch (Exception e) {
                    log.error("批量处理自认证提现记录出现系统错误", e);
                    return ApiResponse.newFailure(CoverChargeErrorCode.SYS_ERROR.getCode(), "系统错误");
                }

                String res = serviceSelfCertificationWithdrawService.batchProcessingWithdrawalRecordPaid(serviceSelfCertificationWithdrawList,
                        adminSinceCertificationBatchMoneyVo.getApprovers());
                if ("".equals(res)) {
                    ApiResponse<Object> response = ApiResponse.newSuccess();
                    response.setMsg("操作成功!");
                    return response;
                } else {
                    return ApiResponse.newFailure(CoverChargeErrorCode.SYS_ERROR.getCode(), res);
                }
            } catch (Exception e) {
                log.error("批量处理自认证提现记录出现系统错误1", e);
                return ApiResponse.newFailure(CoverChargeErrorCode.SYS_ERROR.getCode(), e.getMessage());
            }
        });
    }

    @PostMapping("/allProcessingWithdrawalRecord")
    @ResponseBody
    @ApiOperation(value = "全量处理自认证提现记录", notes = "全量处理自认证提现记录")
    public ApiResponse<?> allProcessingWithdrawalRecord(@RequestBody AdminSinceCertificationBatchMoneyVo adminSinceCertificationBatchMoneyVo) {
        return DRedisLocks.runWithLock(BizConstants.SINCE_CERTIFICATION_WITHDRAWAL, 5000, () -> {
            try {
                String res = serviceSelfCertificationWithdrawService.allProcessingWithdrawalRecordPaid(adminSinceCertificationBatchMoneyVo.getApprovers());
                if ("".equals(res)) {
                    ApiResponse<Object> response = ApiResponse.newSuccess();
                    response.setMsg("全审核操作成功!");
                    return response;
                } else {
                    return ApiResponse.newFailure(CoverChargeErrorCode.SYS_ERROR.getCode(), res);
                }
            } catch (Exception e) {
                log.error("全处理自认证提现记录出现系统错误1", e);
                return ApiResponse.newFailure(CoverChargeErrorCode.SYS_ERROR.getCode(), e.getMessage());
            }
        });
    }

    @PostMapping("/singleIssue")
    @ResponseBody
    @ApiOperation(value = "单笔发放", notes = "单笔发放")
    @RequiresRoles("sso")
    public ApiResponse<?> singleIssue(@RequestBody AdminSinceCertificationIndividualProcessVo adminSinceCertificationIndividualProcessVo) {

        try {
            if (HeavyUtil.isRun(HeavyKeyEnum.WITHDRAWAL_REQUEST.getCode() + adminSinceCertificationIndividualProcessVo.getId())) {
                return ApiResponse.newFailure(CoverChargeErrorCode.SYS_ERROR.getCode(), "频率太快");
            } else {
                String res = serviceSelfCertificationWithdrawService.individualTreatment(adminSinceCertificationIndividualProcessVo);
                if ("".equals(res)) {
                    ApiResponse<Object> response = ApiResponse.newSuccess();
                    response.setMsg("操作成功!");
                    return response;
                } else {
                    return ApiResponse.newFailure(CoverChargeErrorCode.SYS_ERROR.getCode(), res);
                }
            }

        } catch (Exception e) {
            log.error("自认证单笔处理出现错误:提现id:{}", adminSinceCertificationIndividualProcessVo.getId(), e);
            return ApiResponse.newFailure(CoverChargeErrorCode.SYS_ERROR.getCode(), "系统错误");
        } finally {
            HeavyUtil.runDone(HeavyKeyEnum.WITHDRAWAL_REQUEST.getCode() + adminSinceCertificationIndividualProcessVo.getId());
        }
    }

    @GetMapping("/printApplicationForm")
    @ResponseBody
    @ApiOperation(value = "打印申请单", notes = "打印申请单")
    public ApiResponse<?> printApplicationForm(String codeId,
                                               String mobile,
                                               String name,
                                               String platformCode,
                                               Integer status,
                                               Integer type,
                                               Integer invoice,
                                               String startDate,
                                               String endDate,
                                               String id) {
        Integer finalStatus = status;
        return DRedisLocks.runWithLock(BizConstants.SINCE_CERTIFICATION_WITHDRAWAL, 5000, () -> {
            String idCode = codeId;
            if (StringUtils.isNotBlank(mobile)) {
                try {
                    UserInfo userInfo = userDocService.searchUserByIdCodeOrMobile(null, mobile);
                    if (userInfo != null) {
                        idCode = userInfo.getIdCode().toString();
                    }
                } catch (Exception e) {
                    log.info("自认证资金记录根据手机号查询用户信息异常：{}", e.getMessage());
                    throw new ServiceException("根据手机号码获取用户信息失败");
                }
            }
            //查询符合条件的周期记录总数
            IPage<AdminSelfCertificationQueryVo> pageResultTotal = serviceSelfCertificationWithdrawService.queryPageCertificationPaid(new Page<>(1, 1), idCode, name, invoice, platformCode, finalStatus, startDate, endDate, type, id);

            //获取总数
            long count = pageResultTotal.getTotal();
            int page = Math.toIntExact((count / PAGE_SIZE + (count % PAGE_SIZE > 0 ? 1 : 0)));
            //分页获取符合条件页数
            List<SinceCertificationPrintApplicationFormVo> sinceCertificationPrintApplicationFormVoListAll = new ArrayList<>();
            for (int i = 1; i <= page; i++) {
                IPage<AdminSelfCertificationQueryVo> pageResult = serviceSelfCertificationWithdrawService.queryPageCertificationPaid(new Page<>(i, PAGE_SIZE), idCode, name, invoice, platformCode, finalStatus, startDate, endDate, type, id);
                List<AdminSelfCertificationQueryVo> list = pageResult.getRecords();
                sinceCertificationPrintApplicationFormVoListAll.addAll(serviceSelfCertificationWithdrawService.printApplicationForm(list));
            }

            return ApiResponse.newSuccess(sinceCertificationPrintApplicationFormVoListAll);
        });

    }
}
